home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / prolog / sbprolog / amiga / modlibsr.zoo / $decompile.P < prev    next >
Text File  |  1989-08-07  |  21KB  |  621 lines

  1. /************************************************************************
  2. *                                    *
  3. * The SB-Prolog System                            *
  4. * Copyright SUNY at Stony Brook, 1986; University of Arizona,1987    *
  5. *                                    *
  6. ************************************************************************/
  7.  
  8. /*-----------------------------------------------------------------
  9. SB-Prolog is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY.  No author or distributor
  11. accepts responsibility to anyone for the consequences of using it
  12. or for whether it serves any particular purpose or works at all,
  13. unless he says so in writing.  Refer to the SB-Prolog General Public
  14. License for full details.
  15.  
  16. Everyone is granted permission to copy, modify and redistribute
  17. SB-Prolog, but only under the conditions described in the
  18. SB-Prolog General Public License.   A copy of this license is
  19. supposed to have been given to you along with SB-Prolog so you
  20. can know your rights and responsibilities.  It should be in a
  21. file named COPYING.  Among other things, the copyright notice
  22. and this notice must be preserved on all copies. 
  23. ------------------------------------------------------------------ */
  24.  
  25. /* This file contains predicates that traverse a buffer containing
  26.    asserted code, and reconstruct the clause that was asserted.  This
  27.    code is tied fairly tightly to the code generated by "assert", so
  28.    changes to assert may require corresponding updates to this code.
  29.    This also means that compiled code (i.e. that generated by "compile")
  30.    cannot be decompiled.                    */
  31.  
  32. $decompile_export([$clause/2,$clause/3,$listing/1,$instance/2,$listing/0]).
  33.  
  34. $decompile_use($bio, [$writename/1,_,_,$nl/0,_,$tell/1,_,$telling/1,
  35.               $told/0,_,_,_,_,_,_]).
  36. $decompile_use($buff, [_,_,_,$buff_code/4,$symtype/2,_,_,_,_,_,_]).
  37. $decompile_use($bmeta,[_,_,_,_,_,_,_,_,$arity/2,_,_,$mkstr/3,$is_buffer/1]).
  38. $decompile_use($meta,[$functor/3,_,_]).
  39. $decompile_use($assert,[_,_,_,_,_,_,_,_,_,_,$assert_get_prref/2,_,_]).
  40. $decompile_use($blist,[$append/3,_,$memberchk/2,_]).
  41. $decompile_use($deb,[$debug/0,$nodebug/0,_,_,_,_,_,_,_,_,_,$deb_set/3,
  42.          $deb_unset/1]).
  43. $decompile_use($currsym,[_,_,$predicate_property/2,_,_,_,_,_]).
  44.  
  45.  
  46. $clause(Hd,Body) :- $clause(Hd,Body,_,1).
  47.  
  48. $clause(Hd,Body,Ref) :- $clause(Hd,Body,Ref,1).
  49.  
  50. $clause(Hd,Body,Ref,Xform) :-
  51.      nonvar(Hd),
  52.      !,
  53.      $decompile(Hd, Body, Ref, Xform).
  54. $clause(Hd,Body,Ref,Xform) :-
  55.      $is_buffer(Ref),    /* better be a DB ref! */
  56.      $dec_getpsc(Ref,12,_,Psc),
  57.      $mkstr(Psc,Hd0,Arity),
  58.      !,
  59.      $decompile_clause(Ref,Arity,Hd0,Body0),
  60.      (Body0 ?= true ->
  61.           (Hd = Hd0, Body = Body0) ;
  62.       (arg(Arity,Hd0,CutArg),
  63.        $dec_xform(Body0,CutArg,Body,Xform),
  64.        RArity is Arity - 1,
  65.        $functor(Hd0,Pred,_), $functor(Hd,Pred,RArity),
  66.        $dec_copyargs(RArity,Hd0,Hd)
  67.       )
  68.      ).
  69. $clause(Hd,B,R,_) :-
  70.      $telling(X), $tell(user),
  71.      $writename('*** Error: illegal argument(s) to clause/[2,3]: <'), 
  72.      $write(Hd), $write(', '), $write(B), $write(', '), $write(R), $write('> ***'), $nl,
  73.      $told, $tell(X),
  74.      fail.
  75.  
  76. $listing :-
  77.      $predicate_property(X,interpreted),
  78.      $functor(X,P,N),
  79.      $listing(P/N),
  80.      fail.
  81. $listing.
  82.  
  83. $listing(Pred) :- $listing(Pred,1).
  84.  
  85. $listing([],_) :- !.
  86. $listing([H|L],Xform) :-
  87.      !,
  88.      ($listing(H,Xform) -> true ; true),   /* do the rest anyway */
  89.      $listing(L,Xform).
  90. $listing(Pred,Xform) :-
  91.      nonvar(Pred) ->
  92.           (Pred = P/N ->
  93.            ($functor(Hd,P,N),
  94.             ($decompile(Hd,Body,_,Xform),
  95.              $portray_clause((Hd :- Body)),
  96.              fail    /* backtrack to get all clauses */
  97.             ) ;
  98.             true
  99.            ) ;
  100.            ($errmsg('*** Error: argument to listing/1 must be of the form <pred>/<arity>'), $nl
  101.            )
  102.       ) ;
  103.         ($errmsg('*** Error: argument to listing/1 must be instantiated ***'), fail).
  104.  
  105.  
  106. $instance(Ref, Instance) :-
  107.      $is_buffer(Ref) ->
  108.           $instance_1(Ref, Instance) ;
  109.       ($telling(X), $tell(stderr),
  110.        $write('*** Error: argument 1 of instance/2 must be a DB reference ***'), $nl,
  111.        $told, $tell(X),
  112.        fail
  113.       ).
  114.  
  115. $instance_1(Ref, Instance) :-
  116.      $clause(H, B, Ref),
  117.      (H = '_$record_db'(_, Instance) ->
  118.           true ;
  119.       Instance = (H :- B)
  120.      ).
  121.  
  122. $dec_getbuffbyte(Buff,Li,Lo,Byte) :-
  123.     Lo is Li+1, $buff_code(Buff,Li,6 /* gb */,Byte).
  124.  
  125. $dec_getbuffnum(Buff,Li,Lo,Byte) :-
  126.     Lo is Li+4, $buff_code(Buff,Li,5 /* gn */,Byte).
  127.  
  128. $dec_getbuffloat(Buff,Li,Lo,Byte) :-
  129.     Lo is Li+4, $buff_code(Buff,Li,29 /* gf */,Byte).
  130.  
  131. $dec_getpsc(Buff,Li,Lo,Psc) :-
  132.     Lo is Li+4, $buff_code(Buff,Li,28 /* gppsc */, Psc).
  133.  
  134. $decompile(Head, Body, Clref, Xform) :-
  135.      $functor(Head,P,N),
  136.      $symtype(Head, Type),
  137.      (Type =\= 1 ->
  138.           ($dec_errmsg(Type,P,N), fail) ;
  139.       ($dec_GetPrref(Head,Prref),
  140.            $buff_code(Prref,6,8 /* gpb */, FirstClref),
  141.        $clause_addr(FirstClref, Clref,P,N),
  142.        NArity is N + 1,    /* extra argument introduced during assert
  143.                       to handle cuts */
  144.            $functor(NHd,P,NArity),
  145.        $dec_copyargs(N,Head,NHd),
  146.        arg(NArity,NHd,CutArg),
  147.        $decompile_clause(Clref, NArity, NHd, Body0),
  148.        $dec_xform(Body0,CutArg,Body,Xform)
  149.       )
  150.      ).
  151.  
  152. $dec_GetPrref(Head,Prref) :-
  153.      $assert_get_prref(Head, Prref0),
  154.      $dec_getbuffbyte(Prref0,4,_,Op),
  155.      (Op =:= 170 ->        /* clause present, no interception */
  156.           Prref = Prref0 ;
  157.       (Op =:= 231 ->    /* call interception: trace, ET, &c. */
  158.            ($functor(Head,P,N), Pred = P/N,
  159.             $dec_undo_inters(Pred,Inters),
  160.         $dec_GetPrref(Head,Prref),
  161.         $dec_do_inters(Inters,P,N)
  162.            )
  163.      )
  164.      ).
  165.  
  166. $dec_undo_inters(Pred,Inters) :-   /* undo effects of call interception */
  167.      (($symtype('_$traced_preds'(_),TType),
  168.        TType > 0,
  169.        '_$traced_preds'(Pred)
  170.       ) ->
  171.           (Inters = [trace|I0], $deb_unset(Pred)) ;
  172.       Inters = I0
  173.      ),
  174.      (($symtype('_$spy_points'(_),SType),
  175.        SType > 0,
  176.        '_$spy_points'(Pred)
  177.       ) ->
  178.           (I0 = [spy|I1], $deb_unset(Pred)) ;
  179.       I0 = I1
  180.      ),
  181.      (($symtype($deb_ugging(_),DType),
  182.        DType > 0
  183.       ) ->
  184.            (I1 = [debugging(X)], $deb_ugging(X)) ;
  185.        I1 = []
  186.      ).
  187.  
  188. $dec_do_inters([],P,A).
  189. $dec_do_inters([I|IRest],P,A) :-
  190.      $dec_do_inters1(I,P,A), $dec_do_inters(IRest,P,A).
  191.  
  192. $dec_do_inters1(trace,P,A) :- $deb_set(P,A,$deb_trace(_)).
  193. $dec_do_inters1(spy,  P,A) :- $deb_set(P,A,$deb_spy(_)).
  194. $dec_do_inters1(debugging(X),_,_) :- X =:= 1 -> $debug ; $nodebug.
  195.  
  196. /* $clause_addr/4 takes the reference of the first clause for a predicate,
  197.    and returns the reference of a clause for the predicate, backtracking
  198.    successively through all of them.                    */
  199.  
  200. $clause_addr(CurrClref,Clref,P,N) :-
  201.      $buff_code(CurrClref,4,6 /* gb */, Sop),
  202.      ((Sop =:= 162 ; Sop =:= 249) ->     /* trustmeelsefail or noop */
  203.           $clause_addr1(CurrClref,Clref,P,N) ;
  204.       ((Sop =:= 160 ; Sop =:= 161) -> /* trymeelse or retrymeelse */
  205.            ($buff_code(CurrClref,6,8 /* gpb */, NextClref),
  206.             ($clause_addr1(CurrClref,Clref,P,N) ;
  207.          $clause_addr(NextClref, Clref,P,N)  /* get next clause */
  208.         )
  209.            )
  210.      )
  211.      ).
  212.  
  213. $clause_addr1(CurrCl,Cl,P,N) :-
  214.      $buff_code(CurrCl,16,6 /* gb */,179) ->    /* check if SOB-buffer */
  215.          ($buff_code(CurrCl,28,8 /* gpb */,Clref),
  216.       $clause_addr(Clref,Cl,P,N)
  217.      ) ;
  218.      ($buff_code(CurrCl,10,6 /* gb */,240 /* jump */) ->
  219.           ($telling(X), $tell(user),
  220.            $writename('*** Warning: '),
  221.                $writename(P), $writename('/'), $writename(N),
  222.                $writename(' contains compiled code that is not being decompiled ***'), $nl,
  223.                $told, $tell(X),
  224.            fail
  225.           ) ;
  226.           Cl = CurrCl
  227.          ).
  228.  
  229. $decompile_clause(Clref, N, Head, Body) :-
  230.      $buff_code(Clref,10,6 /* gb */, Op),
  231.      Op =\= 248, /* make sure the clause hasn't been erased */
  232.      $dec_mk_rmap(4,4,Rmap0),
  233.      $decompile_head(Clref,1,N,Head,16,Lm,Rmap0,Rmap1),
  234.      $decompile_body(Clref,Body,Lm,Rmap1).
  235.  
  236. $decompile_head(Buff,Arg,Arity,Term,Li,Lo,Rmap0,Rmap1) :-
  237.      Arg > Arity ->
  238.           (Li = Lo, Rmap0 = Rmap1) ;
  239.            ($dec_getbuffbyte(Buff,Li,Lm0,Op),
  240.        $dec_argreg(Op,Buff,Lm0,Reg),
  241.        (Reg =:= Arg ->
  242.             $dec_hdarg(Op,Buff,Term,Lm0,Lm1,Rmap0,Rmap2) ;
  243.         (Lm1 = Li, Rmap2 = Rmap0,
  244.          $dec_map_lookup(Arg,Rmap0,X),
  245.          arg(Arg,Term,X)
  246.         )
  247.        ),
  248.        NextArg is Arg+1,
  249.        $decompile_head(Buff,NextArg,Arity,Term,Lm1,Lo,Rmap2,Rmap1)
  250.       ).
  251.  
  252. $dec_hdarg(3,Buff,Term,Li,Lo,Rmap,Rmap) :-    /* gettval(R1,R2) */
  253.     Li1 is Li+1,    /* skip pad byte */
  254.     $dec_getbuffbyte(Buff,Li1,Lm1,Arg1),
  255.     $dec_getbuffbyte(Buff,Lm1,Lo,Arg2),
  256.     arg(Arg1,Term,T), arg(Arg2,Term,T),
  257.     $dec_map_lookup(Arg1,Rmap,T),
  258.     $dec_map_lookup(Arg2,Rmap,T).
  259. $dec_hdarg(4,Buff,Term,Li,Lo,Rmap,Rmap) :-    /* getcon(Con, N) */
  260.     $dec_getbuffbyte(Buff,Li,Lm,Arg),
  261.     arg(Arg,Term,Const),
  262.     $dec_getpsc(Buff,Lm,Lo,Const),
  263.     $dec_map_lookup(Arg,Rmap,Const).
  264. $dec_hdarg(5,Buff,Term,Li,Lo,Rmap,Rmap) :-    /* getnil(N) */
  265.     $dec_getbuffbyte(Buff,Li,Lo,Arg),
  266.     arg(Arg,Term,[]),
  267.     $dec_map_lookup(Arg,Rmap,[]).
  268. $dec_hdarg(6,Buff,Term,Li,Lo,R0,R1) :-        /* getstr(Str,N) */
  269.     $dec_getbuffbyte(Buff,Li,Lm1,Arg),
  270.     $dec_getpsc(Buff,Lm1,Lm2,Func),
  271.     $mkstr(Func,Str,Arity),
  272.     arg(Arg,Term,Str),
  273.     $dec_subs(1,Arity,Buff,Str,Lm2,Lo,R0,R1),
  274.     $dec_map_lookup(Arg,R1,Str).
  275. $dec_hdarg(7,Buff,Term,Li,Lo,R0,R1) :-        /* getlist(N) */
  276.     $dec_getbuffbyte(Buff,Li,Lm1,Arg),
  277.     List = [_|_], arg(Arg,Term,List),
  278.     $dec_subs(1,2,Buff,List,Lm1,Lo,R0,R1),
  279.     $dec_map_lookup(Arg,R1,List).
  280. $dec_hdarg(14,Buff,Term,Li,Lo,Rmap,Rmap) :-    /* getnumcon(Num, N) */
  281.     $dec_getbuffbyte(Buff,Li,Lm,Arg),
  282.     arg(Arg,Term,N),
  283.     $dec_getbuffnum(Buff,Lm,Lo,N),
  284.     $dec_map_lookup(Arg,Rmap,N).
  285. $dec_hdarg(32,Buff,Term,Li,Lo,Rmap,Rmap) :-    /* getfloatcon(Num, N) */
  286.     $dec_getbuffbyte(Buff,Li,Lm,Arg),
  287.     arg(Arg,Term,N),
  288.     $dec_getbuffloat(Buff,Lm,Lo,N),
  289.     $dec_map_lookup(Arg,Rmap,N).
  290. $dec_hdarg(72,Buff,Term,Li,Lo,Rmap,Rmap) :-    /* getlist_tvar_tvar */
  291.     $dec_getbuffbyte(Buff,Li,Lm0,Arg),
  292.     $dec_getbuffbyte(Buff,Lm0,Lm1,R1),
  293.     $dec_getbuffbyte(Buff,Lm1,Lo,R2),
  294.     $dec_map_lookup(R1,Rmap,A1),
  295.     $dec_map_lookup(R2,Rmap,A2),
  296.     Sub = [A1|A2], arg(Arg,Term,Sub),
  297.     $dec_map_lookup(Arg,Rmap,Sub).
  298. $dec_hdarg(73,Buff,Term,Li,Lo,R0,R1) :-        /* getcomma(N) */
  299.     $dec_getbuffbyte(Buff,Li,Lm1,Arg),
  300.     Sub = ','(_,_), arg(Arg,Term,Sub),
  301.     $dec_subs(1,2,Buff,Sub,Lm1,Lo,R0,R1),
  302.     $dec_map_lookup(Arg,R1,Sub).
  303. $dec_hdarg(74,Buff,Term,Li,Lo,Rmap,Rmap) :-    /* getcomma_tvar_tvar */
  304.     $dec_getbuffbyte(Buff,Li,Lm0,Arg),
  305.     $dec_getbuffbyte(Buff,Lm0,Lm1,R1),
  306.     $dec_getbuffbyte(Buff,Lm1,Lo,R2),
  307.     $dec_map_lookup(R1,Rmap,A1),
  308.     $dec_map_lookup(R2,Rmap,A2),
  309.     Sub = ','(A1,A2), arg(Arg,Term,Sub),
  310.     $dec_map_lookup(Arg,Rmap,Sub).
  311.  
  312. /* $dec_argreg/3 returns the "main" register number for an instruction in
  313.    a buffer.  Argument 1 is the opcode of the "current" instruction. */
  314.  
  315. $dec_argreg(3,Buff,Disp,N) :-            /* gettval(R,N) */
  316.      Lr is Disp + 2,        /* skip pad byte, op1 */
  317.      $buff_code(Buff,Lr,6 /* gb */, N).
  318. $dec_argreg(Op,Buff,Disp,N) :-
  319.      Op >= 4, Op =< 7, /* getcon(C,N)|getnil(N)|getstr(Str,N)|getlist(N) */
  320.      $buff_code(Buff,Disp,6 /* gb */, N).
  321. $dec_argreg(14,Buff,Disp,N) :-            /* getnumcon(Num,N) */
  322.      $buff_code(Buff,Disp,6 /* gb */, N).
  323. $dec_argreg(32,Buff,Disp,N) :-            /* getfloatcon(Num,N) */
  324.      $buff_code(Buff,Disp,6 /* gb */, N).
  325. $dec_argreg(72,Buff,Disp,N) :-            /* getlist_tvar_tvar(N,_,_) */
  326.      $buff_code(Buff,Disp,6 /* gb */, N).
  327. $dec_argreg(73,Buff,Disp,N) :-            /* getcomma(N) */
  328.      $buff_code(Buff,Disp,6 /* gb */, N).
  329. $dec_argreg(74,Buff,Disp,N) :-            /* getcomma_tvar_tvar(N,_,_) */
  330.      $buff_code(Buff,Disp,6 /* gb */, N).
  331. /*  if we hit a "put" instruction we know we're past the head, so return an
  332.     "impossible" register number.                    */
  333. $dec_argreg(15,Buff,Disp,-1).        /* putnumcon(Num,N) */
  334. $dec_argreg(18,Buff,Disp,-1).        /* puttvar(T,R) */
  335. $dec_argreg(20,Buff,Disp,-1).        /* putcon(C,R) */
  336. $dec_argreg(21,Buff,Disp,-1).        /* putnil(R) */
  337. $dec_argreg(22,Buff,Disp,-1).        /* putstr(S,R) */
  338. $dec_argreg(23,Buff,Disp,-1).        /* putlist(R) */
  339. $dec_argreg(35,Buff,Disp,-1).        /* putfloatcon(Num,N) */
  340. $dec_argreg(209,Buff,Disp,-1).        /* movreg(T,R) */
  341. $dec_argreg(235,Buff,Disp,-1).        /* proceed */
  342. $dec_argreg(236,Buff,Disp,-1).        /* execute(P) */
  343.  
  344.  
  345. $dec_subs(N,Arity,Buff,Term,Li,Lo,Rin,Rout) :-
  346.     N > Arity ->
  347.         (Li = Lo, Rin = Rout) ;
  348.     ($dec_getbuffbyte(Buff,Li,Lm1,Op),
  349.      $dec_sub(Op,Buff,Sub,Lm1,Lm2,Rin,Rmid),
  350.      arg(N,Term,Sub),
  351.      N1 is N+1,
  352.      $dec_subs(N1,Arity,Buff,Term,Lm2,Lo,Rmid,Rout)
  353.     ).
  354.  
  355. $dec_sub(10,Buff,X,Li,Lo,Rmap,Rmap) :-        /* unitvar(R) */
  356.     $dec_getbuffbyte(Buff,Li,Lo,R),
  357.     $dec_map_lookup(R,Rmap,X).
  358. $dec_sub(11,Buff,X,Li,Lo,Rmap,Rmap) :-        /* unitval(R) */
  359.     $dec_getbuffbyte(Buff,Li,Lo,R),
  360.     $dec_map_lookup(R,Rmap,X).
  361. $dec_sub(12,Buff,Con,Li,Lo,Rmap,Rmap) :-    /* unicon(Con) */
  362.     Lm is Li+1,    /* skip pad byte */
  363.     $dec_getpsc(Buff,Lm,Lo,Con).
  364. $dec_sub(13,Buff,[],Li,Lo,Rmap,Rmap) :-        /* uninil */
  365.     Lo is Li + 1.
  366. $dec_sub(26,Buff,X,Li,Lo,Rin,Rout) :-        /* bldtvar(R) */
  367.     $dec_getbuffbyte(Buff,Li,Lo,R),
  368.     $dec_map_update(R,Rin,X,Rout).
  369. $dec_sub(27,Buff,X,Li,Lo,Rmap,Rmap) :-        /* bldtval(R) */
  370.     $dec_getbuffbyte(Buff,Li,Lo,R),
  371.     $dec_map_lookup(R,Rmap,X).
  372. $dec_sub(28,Buff,Con,Li,Lo,Rmap,Rmap) :-    /* bldcon(Con) */
  373.     Lm is Li+1,    /* skip pad byte */
  374.     $dec_getpsc(Buff,Lm,Lo,Con).
  375. $dec_sub(29,Buff,[],Li,Lo,Rmap,Rmap) :-        /* bldnil */
  376.     Lo is Li + 1.
  377. $dec_sub(30,Buff,Num,Li,Lo,Rmap,Rmap) :-    /* uninumcon(Num) */
  378.     Lm is Li+1,    /* skip pad byte */
  379.     $dec_getbuffnum(Buff,Lm,Lo,Num).
  380. $dec_sub(31,Buff,Num,Li,Lo,Rmap,Rmap) :-    /* bldnumcon(Num) */
  381.     Lm is Li+1,    /* skip pad byte */
  382.     $dec_getbuffnum(Buff,Lm,Lo,Num).
  383. $dec_sub(34,Buff,Num,Li,Lo,Rmap,Rmap) :-    /* unifloatcon(Num) */
  384.     Lm is Li+1,    /* skip pad byte */
  385.     $dec_getbuffloat(Buff,Lm,Lo,Num).
  386. $dec_sub(35,Buff,Num,Li,Lo,Rmap,Rmap) :-    /* bldfloatcon(Num) */
  387.     Lm is Li+1,    /* skip pad byte */
  388.     $dec_getbuffloat(Buff,Lm,Lo,Num).
  389.  
  390.  
  391. $decompile_body(Buff,Body,Loc,Rmap) :-
  392.      $dec_getbuffbyte(Buff,Loc,Lm0,Op),
  393.      (Op =:= 235 ->                /* proceed */
  394.           Body = true ;
  395.       (Op =:= 236 ->            /* execute(P) */
  396.            (Lm1 is Lm0 + 1,    /* skip pad byte */
  397.             $dec_getpsc(Buff,Lm1,_,Psc),
  398.         $mkstr(Psc,Body,Arity),
  399.         $dec_procputs(Arity,Rmap,Body)
  400.            ) ;
  401.            ($dec_bodyinst(Op,Buff,Lm0,Lm1,Rmap,Rmap0),
  402.             $decompile_body(Buff,Body,Lm1,Rmap0)
  403.            )
  404.       )
  405.      ).
  406.  
  407. $dec_bodyinst(3,Buff,Li,Lo,Rmap,Rmap) :-    /* gettval(R1,R2) */
  408.      Li1 is Li+1,    /* skip pad byte */
  409.      $dec_getbuffbyte(Buff,Li1,Lm1,Arg1),
  410.      $dec_getbuffbyte(Buff,Lm1,Lo,Arg2),
  411.      $dec_map_lookup(Arg1,Rmap,T),
  412.      $dec_map_lookup(Arg2,Rmap,T).
  413. $dec_bodyinst(4,Buff,Li,Lo,Rmap,Rmap) :-    /* getcon(Con, N) */
  414.      $dec_getbuffbyte(Buff,Li,Lm,R),
  415.      $dec_getpsc(Buff,Lm,Lo,Const),
  416.      $dec_map_lookup(R,Rmap,Const).
  417. $dec_bodyinst(5,Buff,Li,Lo,Rmap,Rmap) :-    /* getnil(N) */
  418.      $dec_getbuffbyte(Buff,Li,Lo,R),
  419.      $dec_map_lookup(R,Rmap,[]).
  420. $dec_bodyinst(6,Buff,Li,Lo,Rin,Rout) :-        /* getstr(Str,N) */
  421.      $dec_getbuffbyte(Buff,Li,Lm1,R),
  422.      $dec_getpsc(Buff,Lm1,Lm2,Func),
  423.      $mkstr(Func,Str,Arity),
  424.      $dec_map_lookup(R,Rin,Str),
  425.      $dec_subs(1,Arity,Buff,Str,Lm2,Lo,Rin,Rout).
  426. $dec_bodyinst(7,Buff,Li,Lo,Rin,Rout) :-        /* getlist(N) */
  427.      $dec_getbuffbyte(Buff,Li,Lm1,R),
  428.      List = [_|_],
  429.      $dec_map_lookup(R,Rin,List),
  430.      $dec_subs(1,2,Buff,List,Lm1,Lo,Rin,Rout).
  431. $dec_bodyinst(14,Buff,Li,Lo,Rmap,Rmap) :-    /* getnumcon(Num, N) */
  432.      $dec_getbuffbyte(Buff,Li,Lm,R),
  433.      $dec_getbuffnum(Buff,Lm,Lo,N),
  434.      $dec_map_lookup(R,Rmap,N).
  435. $dec_bodyinst(15,Buff,Li,Lo,Rin,Rout) :-
  436.      $dec_getbuffbyte(Buff,Li,Lm,R),        /* putnumcon(Num,R) */
  437.      $dec_getbuffnum(Buff,Lm,Lo,Num),
  438.      $dec_map_update(R,Rin,Num,Rout).
  439. $dec_bodyinst(18,Buff,Li,Lo,Rin,Rout) :-    /* puttvar(R1, R2) */
  440.      Li1 is Li + 1,
  441.      $dec_getbuffbyte(Buff,Li1,Lm,R1),
  442.      $dec_getbuffbyte(Buff,Lm,Lo,R2),
  443.      $dec_map_update(R1,Rin,X,Rmid),
  444.      $dec_map_update(R2,Rmid,X,Rout).
  445. $dec_bodyinst(20,Buff,Li,Lo,Rin,Rout) :-
  446.      $dec_getbuffbyte(Buff,Li,Lm,R),        /* putcon(Con,R) */
  447.      $dec_getpsc(Buff,Lm,Lo,Con),
  448.      $dec_map_update(R,Rin,Con,Rout).
  449. $dec_bodyinst(21,Buff,Li,Lo,Rin,Rout) :- 
  450.      $dec_getbuffbyte(Buff,Li,Lo,R),        /* putnil(R) */
  451.      $dec_map_update(R,Rin,[],Rout).
  452. $dec_bodyinst(22,Buff,Li,Lo,Rin,Rout) :-
  453.      $dec_getbuffbyte(Buff,Li,Lm0,R),        /* putstr(Str,R) */
  454.      $dec_getpsc(Buff,Lm0,Lm1,Psc),
  455.      $mkstr(Psc,Str,Arity),
  456.      $dec_subs(1,Arity,Buff,Str,Lm1,Lo,Rin,Rmid),
  457.      $dec_map_update(R,Rmid,Str,Rout).
  458. $dec_bodyinst(23,Buff,Li,Lo,Rin,Rout) :- 
  459.      List = [_|_],                /* putlist(R) */
  460.      $dec_getbuffbyte(Buff,Li,Lm,R),
  461.      $dec_map_update(R,Rin,List,Rmid),
  462.      $dec_subs(1,2,Buff,List,Lm,Lo,Rmid,Rout).
  463. $dec_bodyinst(32,Buff,Li,Lo,Rmap,Rmap) :-    /* getfloatcon(Num, N) */
  464.      $dec_getbuffbyte(Buff,Li,Lm,R),
  465.      $dec_getbuffloat(Buff,Lm,Lo,N),
  466.      $dec_map_lookup(R,Rmap,N).
  467. $dec_bodyinst(33,Buff,Li,Lo,Rin,Rout) :-
  468.      $dec_getbuffbyte(Buff,Li,Lm,R),        /* putfloatcon(Num,R) */
  469.      $dec_getbuffloat(Buff,Lm,Lo,Num),
  470.      $dec_map_update(R,Rin,Num,Rout).
  471. $dec_bodyinst(72,Buff,Li,Lo,Rmap,Rmap) :-    /* getlist_tvar_tvar */
  472.      $dec_getbuffbyte(Buff,Li,Lm0,R0),
  473.      $dec_getbuffbyte(Buff,Lm0,Lm1,R1),
  474.      $dec_getbuffbyte(Buff,Lm1,Lo,R2),
  475.      $dec_map_lookup(R1,Rmap,A1),
  476.      $dec_map_lookup(R2,Rmap,A2),
  477.      $dec_map_lookup(R0,Rmap,[A1|A2]).
  478. $dec_bodyinst(73,Buff,Li,Lo,Rin,Rout) :-    /* getcomma(N) */
  479.      $dec_getbuffbyte(Buff,Li,Lm1,R),
  480.      Sub = ','(_,_), $dec_map_lookup(R,Rin,Sub),
  481.      $dec_subs(1,2,Buff,Sub,Lm1,Lo,Rin,Rout).
  482. $dec_bodyinst(74,Buff,Li,Lo,Rmap,Rmap) :-    /* getcomma_tvar_tvar */
  483.      $dec_getbuffbyte(Buff,Li,Lm0,R0),
  484.      $dec_getbuffbyte(Buff,Lm0,Lm1,R1),
  485.      $dec_getbuffbyte(Buff,Lm1,Lo,R2),
  486.      $dec_map_lookup(R1,Rmap,A1),
  487.      $dec_map_lookup(R2,Rmap,A2),
  488.      $dec_map_lookup(R0,Rmap,','(A1,A2)).
  489. $dec_bodyinst(209,Buff,Li,Lo,Rin,Rout) :-  
  490.      Lm0 is Li + 1,    /* skip pad byte */    /* movreg(R1,R2) */
  491.      $dec_getbuffbyte(Buff,Lm0,Lm1,R1),
  492.      $dec_getbuffbyte(Buff,Lm1,Lo,R2),
  493.      $dec_map_lookup(R1,Rin,Val),
  494.      $dec_map_update(R2,Rin,Val,Rout).
  495.  
  496. $dec_procputs(Arg,Rmap,Body) :-
  497.      Arg =:= 0 ->
  498.           true ;
  499.       ($dec_map_lookup(Arg,Rmap,Val),
  500.        arg(Arg,Body,Val),
  501.        Next is Arg - 1,
  502.        $dec_procputs(Next,Rmap,Body)
  503.       ).
  504.  
  505. $dec_xform(Body0,C,Body1,N) :-
  506.      N > 0 -> $dec_xform_1(Body0,C,Body1) ; Body0 = Body1.
  507.  
  508. $dec_xform_1(','(A0,A1,A2,A3),C,(B0,B1,B2,B3)) :-
  509.      !,
  510.      $dec_xform_1(A0,C,B0),
  511.      $dec_xform_1(A1,C,B1),
  512.      $dec_xform_1(A2,C,B2),
  513.      $dec_xform_1(A3,C,B3).
  514. $dec_xform_1(','(A0,A1),C,','(B0,B1)) :-
  515.      !,
  516.      $dec_xform_1(A0,C,B0),
  517.      $dec_xform_1(A1,C,B1).
  518. $dec_xform_1(';'(A0,A1),C,';'(B0,B1)) :-
  519.      !,
  520.      $dec_xform_1(A0,C,B0),
  521.      $dec_xform_1(A1,C,B1).
  522. $dec_xform_1('->'(A0,A1),C,'->'(B0,B1)) :-
  523.      !,
  524.      $dec_xform_1(A0,C,B0),
  525.      $dec_xform_1(A1,C,B1).
  526. $dec_xform_1('_$cutto'(V),C,Lit) :-
  527.      !,
  528.      (C == V -> Lit = '!' ; Lit = '_$cutto'(V)).
  529. $dec_xform_1(L,_,L).
  530.  
  531.  
  532. $dec_errmsg(Type,P,N) :-
  533.      $telling(X), $tell(user),
  534.      $writename('*** Warning: '),
  535.      $writename(P), $writename('/'), $writename(N),
  536.      $dec_errmsg1(Type, ErrType),
  537.      $writename(ErrType), $writename(', cannot decompile ***'), $nl,
  538.      $told, $tell(X).
  539.  
  540. $dec_errmsg1(0, ' is undefined').
  541. $dec_errmsg1(2, ' is compiled').
  542.  
  543. /*  The following predicates manipulate a "register map", which is
  544.     basically an array of 256 elements represented as a complete quadtree
  545.     of height 4.                            */
  546.  
  547. $dec_mk_rmap(Level,Arity,Map) :-
  548.      $functor(Map,rm,Arity),
  549.      (Level =:= 1 ->
  550.          true ;
  551.      (Lev1 is Level - 1,
  552.       $dec_mk_rmaps(Arity,Arity,Lev1,Map)
  553.      )
  554.      ).
  555.  
  556. $dec_mk_rmaps(Argno,Arity,Level,Map) :-
  557.      Argno =:= 0 ->
  558.          true ;
  559.      (arg(Argno,Map,SubMap),
  560.       $dec_mk_rmap(Level,Arity,SubMap),
  561.       NextArg is Argno - 1,
  562.       $dec_mk_rmaps(NextArg,Arity,Level,Map)
  563.      ).
  564.  
  565. $dec_map_lookup(I,Tree,Val) :-
  566.      Index is I - 1,
  567.      $dec_map_lookup(4,Index,Tree,Val).
  568.  
  569. $dec_map_lookup(Level,Index,Tree,Val) :-
  570.     $get_currindex(Level,Index,CurrInd),
  571.     (Level =:= 1 ->
  572.          arg(CurrInd,Tree,Val) ;
  573.      (arg(CurrInd,Tree,SubTree),
  574.       NewLevel is Level - 1,
  575.       $dec_map_lookup(NewLevel,Index,SubTree,Val)
  576.      )
  577.     ).
  578.  
  579. $dec_map_update(I,Tree,Val,NTree) :-
  580.      Index is I-1,
  581.      $dec_map_update(4,Index,Tree,Val,NTree).
  582.  
  583. $dec_map_update(Level,Index,Tree,Val,NTree) :-
  584.     NTree = rm(_,_,_,_),
  585.     $get_currindex(Level,Index,CurrInd),
  586.     (Level =:= 1 ->
  587.      $subst_arg(4,CurrInd,Tree,Val,NTree) ;
  588.      (arg(CurrInd,Tree,SubTree),
  589.       NewLevel is Level - 1,
  590.       $dec_map_update(NewLevel,Index,SubTree,Val,NSubTree),
  591.       $subst_arg(4,CurrInd,Tree,NSubTree,NTree)
  592.      )
  593.      ).
  594.  
  595. $subst_arg(N,I,Tree,Val,NTree) :-
  596.      N =:= 0 ->                /* done! */
  597.           true ;
  598.       ((N =:= I ->            /* make the change */
  599.            arg(N,NTree,Val) ;
  600.            (arg(N,Tree,Arg), arg(N,NTree,Arg))
  601.            ),
  602.        N1 is N - 1,
  603.        $subst_arg(N1,I,Tree,Val,NTree)
  604.       ).
  605.  
  606. $get_currindex(Level,Index,N) :-
  607.     Shift is (Level-1) << 1,  /* Shift = 2*(Level-1) */
  608.     Mask is 2'11 << Shift,
  609.     N is ((Index /\ Mask) >> Shift) + 1.
  610.  
  611. $dec_copyargs(N,T1,T2) :-
  612.      N =:= 0 ->
  613.           true ;
  614.       (arg(N,T1,X), arg(N,T2,X),
  615.        N1 is N - 1,
  616.        $dec_copyargs(N1,T1,T2)
  617.       ).
  618.  
  619. /* ----------------------------- $decompile.P ----------------------------- */
  620.  
  621.